// server.h
// server class header file

#ifndef SERVER_H
#define SERVER_H

#include <SDL/SDL_net.h>
#include <vector>
#include <map>

class ClientData;

class Server;
typedef void (Server::*MessageHandler)(std::vector<std::string>& tokens, 
                                       const char* message, 
                                       const unsigned int sender); 

class Server {
	public:
		Server(const unsigned int, const unsigned int);
		~Server();
		bool addClient();
		unsigned int getNClients();
		
		unsigned int getClientIp(const unsigned int);
		unsigned int getClientPort(const unsigned int);
		unsigned int getNActiveSockets(const unsigned int);
		bool getIsClientConnected(const unsigned int);
		const char* getClientName(const unsigned int);
		unsigned int getClientWizard(const unsigned int);
		void getMessages();		
		
		// Message senders 		
		void sendMap(const unsigned int);
		void sendAddFountain(const unsigned int, const unsigned int,
				             const unsigned int);
		void sendDisconnect(const unsigned int, const char*);
		void sendNewWizard(const unsigned int, const unsigned int, 
						   const unsigned int, const unsigned int);
		void sendNewClientInfo(const unsigned int client, 
							   const unsigned int clientId, 
							   const bool isConnected, const char* name);
		void sendChat(const unsigned int client, const char* chat);
		void sendYou(const unsigned int client);
		void sendNewTurn(const unsigned int wizard);
		void sendNewPhase(const unsigned int phase);
		void sendNewRound();
		void sendMove(const unsigned int wizard, const unsigned int x, 
						  const unsigned int y);
		
	private:
		unsigned int getNAliveClients();
		void removeClient(const unsigned int);
		unsigned int receiveData(void*, const unsigned int, const unsigned int);
		unsigned int sendData(const void*, const unsigned int,
		                      const unsigned int);
		void sendAllData(const void*, const unsigned int);
		bool sendMessage(const char* message, const unsigned int client);
		void sendAllMessage(const char* message);
		void invalidMessage(const char* message, const char* reason, 
                            const unsigned int sender);
		void parseMessage(char* message, const unsigned int bufferSize,
			              const unsigned int sender);
		
		// Message handlers
		void getMap(std::vector<std::string>& tokens, const char* message,
		            const unsigned int sender);
		void recvDisconnect(std::vector<std::string>& tokens,
		                    const char* message, const unsigned int sender);
		void recvChat(std::vector<std::string>& tokens, const char* message,
		              const unsigned int sender);
		void recvMove(std::vector<std::string>& tokens, const char* message,
		              const unsigned int sender);
		
		TCPsocket serverSocket_;
		unsigned int maxSockets_;
		unsigned int maxClients_;
		std::vector<ClientData*> clients_;
		SDLNet_SocketSet socketSet_;
		
		std::map<std::string, MessageHandler, 
			std::less<std::string> >  messageHandlers_;
};

class ClientData {
	public:
		TCPsocket socket;
		IPaddress ip;
		char *buffer;
		unsigned int messageLen;

		bool isConnected;
		char *name;
};

#endif // SERVER_H
